
`include "defines.v"

module clint(
    input  wire clk,
	input  wire rst,

    input mem_valid,
    input [63:0]  mem_addr,
    input [1:0] mem_size,
    input mem_load_en,
    input mem_save_en,
    input [63:0] mem_data,

    output reg [63:0] clint_data_read,
	//output clint_done,

	output wire clint_raise_interruption

    );
	//wire writable = csr_w_ena && (csr_w_addr[11:10] != 2'b11);
	/*
	reg [7:0]k;
	always @(posedge clk) begin
		if (rst == 1'b1) begin
			k <= 8'd49;
		end
		else begin
			if (k == 8'd4) begin
				k <= 0;
			end
			else begin
				k <= k+1;
			end
		end
	end
	reg clk_d;
	always @(posedge clk) begin
		if (rst == 1'b1) begin
			clk_d <= 1'b0;
		end
		else if (k == 8'd4) begin
			clk_d <= ~clk_d;
		end
	end
	*/

	//mtime
	reg [`REG_BUS] mtime;
	always @(posedge clk)
	begin
		if (rst == 1'b1) begin
			mtime <= `ZERO_WORD;
		end
		else if ((mem_valid == 1'b1) && (mem_save_en == 1'b1)) begin	
			if(mem_addr==64'h200bff8)begin
				if (mem_size == 2'b00) begin
					mtime[7:0] <= mem_data[7:0];
				end
				else if (mem_size == 2'b01) begin
					mtime[15:0] <= mem_data[15:0];
				end
				else if (mem_size == 2'b10) begin
					mtime[31:0] <= mem_data[31:0];
				end
				else if (mem_size == 2'b11) begin
					mtime[63:0] <= mem_data[63:0];
				end
			end
		end
		else begin
			mtime <= mtime + 1;
		end
	end

	//mtimecmp
	reg [`REG_BUS] mtimecmp;
	always @(posedge clk)
	begin
		if (rst == 1'b1) begin
			mtimecmp <= `ZERO_WORD;
		end
		else if ((mem_valid == 1'b1) && (mem_save_en == 1'b1)) begin	
			if(mem_addr==64'h2004000)begin
				if (mem_size == 2'b00) begin
					mtimecmp[7:0] <= mem_data[7:0];
				end
				else if (mem_size == 2'b01) begin
					mtimecmp[15:0] <= mem_data[15:0];
				end
				else if (mem_size == 2'b10) begin
					mtimecmp[31:0] <= mem_data[31:0];
				end
				else if (mem_size == 2'b11) begin
					mtimecmp[63:0] <= mem_data[63:0];
				end
			end
		end
		else begin
			mtimecmp <= mtimecmp;
		end
	end

	assign clint_raise_interruption = (mtime >= mtimecmp);
	//always @(posedge clk) begin
		//clint_raise_interruption <= (mtime >= mtimecmp);  //for efficiency
	//end
	//read module, combinational
	always @(*) begin
		if (rst == 1'b1) begin
			clint_data_read = `ZERO_WORD;
			//clint_done = 1'b0;
		end
		else if ((mem_valid == 1'b1) && (mem_load_en == 1'b1)) begin
			if (mem_addr == 64'h200bff8) begin
				clint_data_read = mtime;
				//clint_done = 1'b1;
			end
			else if (mem_addr == 64'h2004000) begin
				clint_data_read = mtimecmp;
				//clint_done = 1'b1;
			end
			else begin
				clint_data_read = `ZERO_WORD;
				//clint_done = 1'b0;
			end
		end
		else begin
			clint_data_read = `ZERO_WORD;
			//clint_done = 1'b0;
		end
	end


endmodule
